/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin			*/
/*	Project:	GlbKv-1.0.0			*/
/*	Author:		gong_libin			*/
/*	Date:		2013_09_25			*/
/*	File:		GlbKvUdpTest.cpp		*/
/********************************************************/

#include "GlbKv.h"

#define	GLB_KU_NUM			10000
#define	GLB_KU_PORT			const_cast<char*>("20911")
#define	GLB_KU_ADDR			const_cast<char*>("127.0.0.1")

int main(int argc, char* argv[])
{
	int iCount = 1;
 	int iIndex = 0;
	int iReturn = 0;
	UCHAR ucType = 0;
	GlbNet::CGlbUdp CUdp;
	GlbNet::CGlbPro CSend;
	GlbNet::CGlbPro CRecv;
	GlbCls::CGlbTime CTime;
	char szKey[GLB_PACKET] = { 0 };
	char szVal[GLB_PACKET] = { 0 };
	char szBuf[GLB_PACKET] = { 0 };
	UCHAR uszSend[GLB_KBYTES8] = { 0 };
	UCHAR uszRecv[GLB_KBYTES8] = { 0 };
	GlbNet::GLBPROKV_S stRecv[GLB_KV_PAIR] = {{'\0', 0, NULL}};
	GlbNet::GLBPROKV_S stSend[GLB_KV_PAIR] = {{GLB_KV_KEY, 0, (UCHAR*)szKey}, {GLB_KV_VAL, 0, (UCHAR*)szVal}};
	GlbNet::GLBPROHEAD_S stHead = {
		GLB_PRO_FLAG,
		GLB_PRO_1,
		GLB_PRO_DATA,
		GLB_PRO_0,
		GLB_PRO_Y,
		GLB_PRO_0,
		GLB_PRO_0,
		GLB_PRO_0,
		GLB_PRO_0,
		GLB_DEF_SUCC,
		GLB_PRO_0,
		GLB_PRO_0,
	};

	struct option stOptions[] = {
		{"insert", 0, 0, 'i'},
		{"select", 0, 0, 's'},
		{"delete", 0, 0, 'd'},
		{"help", 0, 0, 'h'},
		{0, 0, 0, 0},
	};

	if (argc < 2) {
		GLB_PRINT("Usage: %s [insert|select|delete]\n", argv[0]);
		return GLB_SUCCESS;
	}

	while (true) {
		iReturn = getopt_long(argc, argv, "isdh", stOptions, &iIndex);
		if (iReturn < 0) {
			break;
		}
		switch (iReturn) {
			case 'i':
				ucType = GLB_DEF_INST;
				break;
			case 's':
				ucType = GLB_DEF_SELT;
				break;
			case 'd':
				ucType = GLB_DEF_DELT;
				break;
			case 'h':
				GLB_PRINT("Usage: %s [insert|select|delete]\n", argv[0]);
				return GLB_SUCCESS;
			default:
				return GLB_SUCCESS;
		}
	}

	CTime.GlbTimeOn();

	for (; iCount < GLB_KU_NUM; iCount ++) {
		sprintf(szKey, "%d", iCount);
		stSend[0].m_iLength = strlen(szKey);

		switch (ucType) {
			case GLB_DEF_INST:
				sprintf(szVal, "Val: %d+", iCount);
				memset(szVal + strlen(szVal), 'A', GLB_BUFFER);
				stSend[1].m_iLength = strlen(szVal);
				stHead.m_ucVerb = GLB_DEF_INST;
				stHead.m_usTotal = GLB_KV_VAL;
				break;
			case GLB_DEF_SELT:
				stHead.m_ucVerb = GLB_DEF_SELT;
				stHead.m_usTotal = GLB_KV_KEY;
				break;
			case GLB_DEF_DELT:
				stHead.m_ucVerb = GLB_DEF_DELT;
				stHead.m_usTotal = GLB_KV_KEY;
				break;
			default:
				break;
		}

		CSend.GlbProPutBody(NULL);
		CSend.GlbProInduce(&stHead);
		CSend.GlbProPutLength(GlbProKvOutput(stSend, stHead.m_usTotal, &uszSend[GLB_PRO_HEAD], GLB_KBYTES8 - GLB_PRO_HEAD));
		CSend.GlbProCreate(uszSend, GLB_KBYTES8);

		if (GLB_SUCCESS == CUdp.GlbNetInitSend(GLB_KU_ADDR, GLB_KU_PORT)) {
			CUdp.GlbNetSetTimeOut(GLB_TIMEOUT, 0);
			if (CUdp.GlbNetSend(uszSend, GLB_PRO_HEAD + CSend.GlbProGetLength()) > 0) {
				if ((CUdp.GlbNetRecv(uszRecv, GLB_KBYTES8)) > 0) {
					CRecv.GlbProReset();
					CRecv.GlbProParse(uszRecv, GLB_PRO_HEAD);
					CRecv.GlbProDisplay();
					if (GLB_DEF_SUCC == CRecv.GlbProGetResult()) {
						GLB_PRINT("Result[%08d]: success\n", iCount);
						if (CRecv.GlbProGetLength() > 0) {
							memset(stRecv, '\0', sizeof(GlbNet::GLBPROKV_S) * GLB_KV_PAIR);
							GlbProKvInput(stRecv, GLB_KV_PAIR, &uszRecv[GLB_PRO_HEAD], GLB_KBYTES8 - GLB_PRO_HEAD);
							memcpy(szBuf, stRecv[1].m_puszValue, stRecv[1].m_iLength);
							GLB_PRINT("Val[%08d]: %s\n", iCount, szBuf);
						}
					}
					else {
						GLB_PRINT("Result[%08d]: failure\n", iCount);
					}
				}
				else {
					GLB_ERROR("Failed[%08d] to GlbNetRecv\n", iCount);
				}
			}
			else {
				GLB_ERROR("Failed[%08d] to GlbNetSend\n", iCount);
			}
			CUdp.GlbNetClose();
		}
	}

	CTime.GlbTimeOff();
	CTime.GlbTimeDisplay();

	return GLB_SUCCESS;
}
